package org.springblade.modules.system.service.impl;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.modules.repair.dto.UserTrajectoryDTO;
import org.springblade.modules.repair.entity.MaintainWxmsgType;
import org.springblade.modules.repair.entity.UserTrajectory;
import org.springblade.modules.repair.enums.BuildingCacheEnum;
import org.springblade.modules.repair.enums.UserTrajectoryEnum;
import org.springblade.modules.repair.mapper.UserTrajectoryMapper;
import org.springblade.modules.repair.service.IBuildingService;
import org.springblade.modules.repair.service.IMaintainMalfunctionWorkService;
import org.springblade.modules.repair.service.IMaintainPlanContentService;
import org.springblade.modules.repair.service.IMaintainWxmsgTypeService;
import org.springblade.modules.repair.utils.DistanceUtils;
import org.springblade.modules.repair.utils.MapUtil;
import org.springblade.modules.repair.vo.BuildingRedisVO;
import org.springblade.modules.repair.vo.plan.wx.WxUserPlanVo;
import org.springblade.modules.system.service.IUserTrajectoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: Sharry
 * @createTime: 2023/4/26 15:42
 * @version: Version-1.0
 */
@Service
@Slf4j
public class UserTrajectoryServiceImpl extends BaseServiceImpl<UserTrajectoryMapper, UserTrajectory> implements IUserTrajectoryService {

	@Autowired
	private IBuildingService buildingService;

	@Autowired
	private BladeRedis bladeRedis;


	@Autowired
	@Lazy
	private IMaintainMalfunctionWorkService malfunctionWorkService;

	@Autowired
	@Lazy
	private IMaintainWxmsgTypeService maintainWxmsgTypeService;




	@Async
	@Override
	public void record(UserTrajectoryDTO userTrajectoryDTO) {
		// 2. 根据传入的 坐标 获取所在项目（建筑）
		String prefix = BuildingCacheEnum.BUILDING_REDIS_LIST.getKey();
		String tenantId = userTrajectoryDTO.getTenantId();
		String key = prefix + tenantId;

		Boolean exists = bladeRedis.exists(key);
		if (Boolean.FALSE.equals(exists)) {
			log.info("即将进行缓存刷新：" + key);
			// 获取目标对象列表
			List<BuildingRedisVO> l = buildingService.listForVO();
			bladeRedis.del(key);
			// 执行
			l.forEach(b -> bladeRedis.lPush(key, JSON.toJSONString(b)));
		}
		List<BuildingRedisVO> buildingList = new ArrayList<>();
		// 类型转换
		Object[] redisBuildings = bladeRedis.lRange(key, 0, -1).toArray();
        for (Object redisBuilding : redisBuildings) {
            JSONArray jsonArray = JSONUtil.parseArray(redisBuilding);
            Object[] objects = jsonArray.toArray();
            for (Object object : objects) {
                JSONObject jsonObject = JSONUtil.parseObj(object);
                BuildingRedisVO buildingRedisVO = JSONUtil.toBean(jsonObject, BuildingRedisVO.class);
                buildingList.add(buildingRedisVO);
            }
        }
		double distance = 1000;
		double userLongitude = Double.parseDouble(userTrajectoryDTO.getLongitude());
		double userLatitude = Double.parseDouble(userTrajectoryDTO.getLatitude());
		String buildingName = null;
		Long buildingId = null;
		// 遍历计算
		for (BuildingRedisVO b : buildingList) {
			double bLongitude = b.getLongitude().doubleValue();
			double bLatitude = b.getLatitude().doubleValue();
			// 计算
			double bDistance = DistanceUtils.getDistance(userLongitude, userLatitude, bLongitude, bLatitude).doubleValue();
			if (bDistance <= distance) {
				distance = bDistance;
				buildingName = b.getName();
				buildingId = b.getId();
			}
		}
		userTrajectoryDTO.setBuildingId(buildingId);
		userTrajectoryDTO.setBuildingName(buildingName);
		// 3. 复制并插入数据库
		UserTrajectory userTrajectory = copy(userTrajectoryDTO);
		save(userTrajectory);

		//异步发送签到签退的消息提醒
//		WxUserPlanVo userPlanVo = new WxUserPlanVo();
//		userPlanVo.setUserId(AuthUtil.getUserId());
//		userPlanVo.setLongitude(userTrajectoryDTO.getLongitude());
//		userPlanVo.setLatitude(userTrajectoryDTO.getLatitude());
//		wxSendMsg(userPlanVo);
		// 2024-11-13 直接返回 true，异步处理
	}

	/**
	 * 单个方法不超 80 行，拆分 手动赋值
	 *
	 * @param userTrajectoryDTO 源
	 * @return 目标实体
	 */
	private UserTrajectory copy(UserTrajectoryDTO userTrajectoryDTO) {
		UserTrajectory userTrajectory = new UserTrajectory();
		// 手动赋值
		userTrajectory.setUserId(userTrajectoryDTO.getUserId());
		userTrajectory.setRealName(userTrajectoryDTO.getRealName());
		userTrajectory.setLongitude(userTrajectoryDTO.getLongitude());
		userTrajectory.setLatitude(userTrajectoryDTO.getLatitude());
		userTrajectory.setDeptIdList(userTrajectoryDTO.getDeptIdList());
		userTrajectory.setDeptNameAll(userTrajectoryDTO.getDeptNameAll());
		userTrajectory.setPlanId(userTrajectoryDTO.getPlanId());
		userTrajectory.setBuildingId(userTrajectoryDTO.getBuildingId());
		userTrajectory.setBuildingName(userTrajectoryDTO.getBuildingName());
		userTrajectory.setOperation(userTrajectoryDTO.getOperation());
		userTrajectory.setRecordType(userTrajectoryDTO.getRecordType());
		userTrajectory.setTypeStatus(userTrajectoryDTO.getTypeStatus());
		userTrajectory.setTenantId(userTrajectoryDTO.getTenantId());
		userTrajectory.setFromType(userTrajectoryDTO.getFromType());
		return userTrajectory;
	}

	/**
	 * 维修预警
	 * 发送签到 签退的消息
	 *
	 * @param wxUserPlanVo
	 */
	@Async
	public void wxSendMsg(WxUserPlanVo wxUserPlanVo) {
		MaintainWxmsgType detail = maintainWxmsgTypeService.getOne(Wrappers.<MaintainWxmsgType>lambdaQuery().eq(MaintainWxmsgType::getTenantId, AuthUtil.getTenantId()));

		//不再上报时间范围内不提醒
		if (detail.getGpsBegeinTime() == null || detail.getGpsBegeinTime() == null) {
			return;
		}
		if (!(detail.getGpsBegeinTime().getTime() > System.currentTimeMillis() && System.currentTimeMillis() < detail.getGpsEndTime().getTime())) {
			return;
		}
		List<WxUserPlanVo> wxUserPlanVos = malfunctionWorkService.userPlanListOfToday(null);
		if (wxUserPlanVos.size() > 0) {
			List<WxUserPlanVo> planVos = wxUserPlanVos.stream().filter(o -> o.getUserId().equals(wxUserPlanVo.getUserId())).collect(Collectors.toList());
			if (planVos != null & planVos.size() > 0) {
				List<WxUserPlanVo> signList = new ArrayList<>();
				List<WxUserPlanVo> signOutList = new ArrayList<>();
				for (WxUserPlanVo wxUserPlanVo1 : planVos) {
					try {
						Integer distance = MapUtil.getDistance(MapUtil.getLongitude(wxUserPlanVo1.getLongitude()), MapUtil.getLatitude(wxUserPlanVo1.getLatitude()), MapUtil.getLongitude(wxUserPlanVo.getLongitude()), MapUtil.getLatitude(wxUserPlanVo.getLatitude()));
						if (wxUserPlanVo1.getSignOutTime() != null) {
							if (detail.getPlanSignM() < distance) {
								signList.add(wxUserPlanVo1);
							}
						} else {
							if (detail.getPlanSignOutM() < distance) {
								//发送签退逻辑
								signOutList.add(wxUserPlanVo1);
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}



				if(signList.size()>0){
					//发送签到逻辑
				}
				if(signOutList.size()>0){
					//发送签退逻辑
				}
			}
		}
	}
}
